﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Retete.Models;
using Retete.ViewModels;
using System.IO;
using System.Globalization;
using System.Configuration;
using System.Diagnostics;
using Retete.Helpers;

namespace Retete.Controllers
{
    public class InventarController : Controller
    {
        private ReteteEntities entities = new ReteteEntities();

        public ActionResult Index(int? year, int? month, int? day)
        {
            if (day.HasValue == true)
            {
                DateTime selectedDate = new DateTime(year.Value, month.Value, day.Value);
                List<StocViewModel> selectieInventar = Rapoarte.GenereazaStoc(selectedDate);

                return View(new InventarViewModel(selectieInventar) { SelectedDate = selectedDate });
            }
            else return View(new InventarViewModel(Rapoarte.GenereazaStoc(DateTime.Today)) { SelectedDate = DateTime.Today });
        }
        public ActionResult Create()
        {
            Produs selectie = entities.Produse.OrderByDescending(element => element.Cod).FirstOrDefault();

            if (selectie != null) return View(new ProdusViewModel() { CodUltimulProdus = selectie.Cod });
            else return View(new ProdusViewModel());
        }
        public ActionResult Edit()
        {
            Produs selectie = entities.Produse.OrderByDescending(element => element.Cod).FirstOrDefault();

            if (selectie == null) return View(new InventarViewModel(Rapoarte.GenereazaStoc(DateTime.Today)));
            else return View(new InventarViewModel(Rapoarte.GenereazaStoc(DateTime.Today)) { CodUltimulProdus = selectie.Cod });
        }
        public ActionResult Delete(int id)
        {
            Produs selectie = entities.Produse.FirstOrDefault(element => element.ID == id);

            if (selectie == null) return RedirectToAction("Index");
            else
            {
                List<RetetaProdus> referinte = entities.ReteteProduse.Where(element => element.IDProdus == id).ToList();
                return View(new StergeProdusViewModel() { Produs = selectie, Referinte = referinte });
            }
        }
        public ActionResult ExportExcel()
        {
            List<StocViewModel> inventar = Rapoarte.GenereazaStoc(DateTime.Today);
            string continut = string.Empty;

            using (StringWriter writer = new StringWriter())
            {
                writer.WriteLine("<html>");
                writer.WriteLine("  <head>");
                writer.WriteLine("      <title>Inventar</title>");
                writer.WriteLine("      <script type='text/javascript'>window.print()</script>");
                writer.WriteLine("  </head>");
                writer.WriteLine("  <body style='font-family: Calibri; font-size: 11pt; color: #999999'>");
                writer.WriteLine("  <h1 style='font-size: 16pt'>Inventarul produselor la data " + DateTime.Today.ToString("dd/MM/yyyy") + "</h1>");
                writer.WriteLine("      <table>");
                writer.WriteLine("          <tr>");
                writer.WriteLine("              <td style='width: 100px; font-weight: bold;'>Cod</td>");
                writer.WriteLine("              <td style='width: 400px; font-weight: bold;'>Produs</td>");
                writer.WriteLine("              <td style='width: 100px; font-weight: bold;'>Cantitate</td>");
                writer.WriteLine("          </tr>");

                foreach (StocViewModel element in inventar)
                {
                    writer.WriteLine("          <tr>");
                    writer.WriteLine("              <td>" + element.Cod + "</td>");
                    writer.WriteLine("              <td>" + element.Nume + "</td>");
                    writer.WriteLine("              <td>" + element.Cantitate.ToString("0.00", CultureInfo.InvariantCulture) + "</td>");
                    writer.WriteLine("          </tr>");
                }

                writer.WriteLine("      </table>");
                writer.WriteLine("  </body>");
                writer.WriteLine("</html>");
                writer.Flush();

                return Content(writer.ToString());
            }
        }

        [HttpPost]
        public ActionResult Create(ProdusViewModel result)
        {
            if (string.IsNullOrEmpty(result.ProdusNouNume) == true) ModelState.AddModelError("ProdusNouNume", "Numele produsului este obligatoriu");
            if (string.IsNullOrEmpty(result.ProdusNouCod) == true) ModelState.AddModelError("ProdusNouCod", "Codul produsului este obligatoriu");
            if (string.IsNullOrEmpty(result.ProdusNouUnitateMasura) == true) ModelState.AddModelError("ProdusNouUnitateMasura", "Unitatea de masura este obligatorie");
            if (string.IsNullOrEmpty(result.ProdusNouCategorie) == true) ModelState.AddModelError("ProdusNouCategorie", "Categoria este obligatorie");
            if (entities.Produse.Any(element => element.Nume == result.ProdusNouNume) == true) ModelState.AddModelError("ProdusNouNume", "Produsul exista deja");

            if (ModelState.IsValid == true)
            {
                Produs nou = new Produs() { Cod = result.ProdusNouCod, Categorie = result.ProdusNouCategorie, Nume = result.ProdusNouNume, UnitateMasura = result.ProdusNouUnitateMasura };
                entities.AddToProduse(nou);
                entities.SaveChanges();

                return RedirectToAction("Index");
            }
            else return View(result);
        }

        [HttpPost]
        public ActionResult Edit(InventarViewModel result)
        {
            if (string.IsNullOrEmpty(result.ProdusNouNume) == false)
            {
                if (string.IsNullOrEmpty(result.ProdusNouCod) == true) ModelState.AddModelError("ProdusNouCod", "Codul este obligatoriu");
                if (string.IsNullOrEmpty(result.ProdusNouCategorie) == true) ModelState.AddModelError("ProdusNouCategorie", "Categoria este obligatorie");
                if (string.IsNullOrEmpty(result.ProdusNouUnitate) == true) ModelState.AddModelError("ProdusNouUnitate", "Unitatea de masura este obligatorie");

                if (result.Stoc != null)
                {
                    if (result.Stoc.Any(element => element.Cod == result.ProdusNouCod) == true) ModelState.AddModelError("ProdusNouCod", "Mai exista un produs cu acest cod");
                    if (result.Stoc.Any(element => element.Nume == result.ProdusNouNume) == true) ModelState.AddModelError("ProdusNouNume", "Mai exista un produs cu acest nume");
                }
                
                if (ModelState.IsValid == true)
                {
                    if (result.Stoc == null) result.Stoc = new List<StocViewModel>();
                    result.Stoc.Add(new StocViewModel() { Cod = result.ProdusNouCod, Nume = result.ProdusNouNume, Categorie = result.ProdusNouCategorie, UnitateMasura = result.ProdusNouUnitate, Cantitate = result.ProdusNouCantitate, PretCumparare = result.ProdusNouPret, Pret = result.ProdusNouPretVanzare });

                    result.ProdusNouCod = string.Empty;
                    result.ProdusNouNume = string.Empty;
                    result.ProdusNouCategorie = string.Empty;
                    result.ProdusNouUnitate = string.Empty;
                    result.ProdusNouPret = 0;
                    result.ProdusNouPretVanzare = 0;
                    result.ProdusNouCantitate = 0;
                    result.FocusProdusNou = true;
                    ModelState.Clear();
                }

                return View(result);
            }
            else
            {
                ElementStoc ultimulElement = entities.Stoc.OrderByDescending(element => element.Data).FirstOrDefault();
                List<ElementStoc> cantitatiCasate = new List<ElementStoc>();

                // actualizez stocul
                foreach (StocViewModel element in result.Stoc)
                {
                    if (element.ID == 0)
                    {
                        Produs produsNou = new Produs() { Nume = element.Nume, Categorie = element.Categorie, Cod = element.Cod, Pret = element.Pret, PretCumparare = element.PretCumparare, UnitateMasura = element.UnitateMasura };

                        entities.AddToProduse(produsNou);
                        entities.AddToStoc(new ElementStoc() { Produs = produsNou, Cantitate = element.Cantitate, Data = DateTime.Today });
                    }
                    else if (ultimulElement != null && ultimulElement.Data == DateTime.Today)
                    {
                        ElementStoc selectie = entities.Stoc.First(stoc => stoc.IDProdus == element.ID && stoc.Data == DateTime.Today);
                        if (element.CantitateTeoretica > element.Cantitate) cantitatiCasate.Add(new ElementStoc() { IDProdus = element.ID, Cantitate = element.CantitateTeoretica - element.Cantitate, Data = DateTime.Today, Produs = new Produs() { ID = element.ID, Nume = element.Nume, Categorie = element.Categorie, Cod = element.Cod, Pret = element.Pret, PretCumparare = element.PretCumparare, UnitateMasura = element.UnitateMasura } });

                        selectie.Cantitate = element.Cantitate;
                        selectie.Produs.PretCumparare = element.PretCumparare;
                        selectie.Produs.Pret = element.Pret;
                    }
                    else
                    {
                        Produs selectie = entities.Produse.First(filtru => filtru.ID == element.ID);
                        if (element.CantitateTeoretica > element.Cantitate) cantitatiCasate.Add(new ElementStoc() { IDProdus = element.ID, Cantitate = element.CantitateTeoretica - element.Cantitate, Data = DateTime.Today, Produs = new Produs() { ID = element.ID, Nume = element.Nume, Categorie = element.Categorie, Cod = element.Cod, Pret = element.Pret, PretCumparare = element.PretCumparare, UnitateMasura = element.UnitateMasura } });

                        entities.AddToStoc(new ElementStoc() { IDProdus = element.ID, Cantitate = element.Cantitate, Data = DateTime.Today });
                        selectie.Pret = element.Pret;
                        selectie.PretCumparare = element.PretCumparare;
                    }
                }

                // salvez modificarile
                entities.SaveChanges();

                // tiparesc raportul de produse casate
                if (cantitatiCasate.Count > 0) return Content(Rapoarte.GenereazaRaportProduseCasate(cantitatiCasate));
                else return RedirectToAction("Index");
            }
        }

        [HttpPost]
        public ActionResult Delete(StergeProdusViewModel result)
        {
            if (string.IsNullOrEmpty(result.NumeProdusInlocuitor) == false && result.IDProdusInlocuitor == 0) ModelState.AddModelError("NumeProdusInlocuitor", "Nu ati selectat corect produsul");
            if (entities.ReceptiiProduse.Any(element => element.IDProdus == result.Produs.ID) == true && result.IDProdusInlocuitor == 0) ModelState.AddModelError("ProdusCod", "Exista receptii pe acest produs. Produsul poate fi doar inlocuit.");
            if (entities.ElementeVanzari.Any(element => element.IDProdus == result.Produs.ID) == true && result.IDProdusInlocuitor == 0) ModelState.AddModelError("ProdusCod", "Exista vanzari pe acest produs. Produsul poate fi doar inlocuit.");
            if (entities.ElementeVanzari.Any(element => element.Reteta.Produse.Any(filtru => filtru.Produs.ID == result.Produs.ID) == true) == true && result.IDProdusInlocuitor == 0) ModelState.AddModelError("ProdusCod", "Exista vanzari pe acest produs. Produsul poate fi doar inlocuit.");

            if (ModelState.IsValid == true)
            {
                Produs selectie = null;
                if (string.IsNullOrEmpty(result.NumeProdusInlocuitor) == false) selectie = entities.Produse.FirstOrDefault(element => element.ID == result.IDProdusInlocuitor);

                // inlocuiesc produsul in retete, vanzari si receptii
                if (selectie != null)
                {
                    foreach (RetetaProdus retetaProdus in entities.ReteteProduse.Where(element => element.IDProdus == result.Produs.ID)) retetaProdus.IDProdus = result.IDProdusInlocuitor;
                    foreach (ReceptieProdus receptieProdus in entities.ReceptiiProduse.Where(element => element.IDProdus == result.Produs.ID)) receptieProdus.IDProdus = result.IDProdusInlocuitor;
                    foreach (ElementVanzare elementVanzare in entities.ElementeVanzari.Where(element => element.IDProdus == result.Produs.ID)) elementVanzare.IDProdus = result.IDProdusInlocuitor;
                }

                // sterg produsul din stoc si din produse
                foreach (ElementStoc elementStoc in entities.Stoc.Where(element => element.IDProdus == result.Produs.ID)) entities.DeleteObject(elementStoc);
                entities.DeleteObject(entities.Produse.First(element => element.ID == result.Produs.ID));

                entities.SaveChanges();
                return RedirectToAction("Index");
            }
            else return View(result);
        }
    }
}